import json

from django.http import JsonResponse, HttpResponse
# 书本的列表视图
from django.views import View
from rest_framework.decorators import action
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from rest_framework.views import APIView

from booktest.models import BookInfo
from booktest.serializers import BookInfoSerializer, BookInfo01Serializer


# Create your views here.


class BookInfoListView(View):
    '''
    书本的列表视图
    '''

    def get(self, request):
        '''
        获取书本列表
        :param request:
        :return:
        '''
        books = BookInfo.objects.all()
        # 将 Queryset 封装成字典
        result = []
        for book in books:
            book_dict = {
                'id' : book.id,
                'btitle' : book.btitle,
                'bpub_date' : book.bpub_date,
                'bread' : book.bread,
                'bcomment' : book.bcomment,
            }

            result.append(book_dict)

        return JsonResponse(data=result, safe=False)
        pass

    def post(self, request):
        '''
        新增书籍
        :return:
        '''
        # 从前端获取数据，
        book_dict = json.loads(request.body.decode())
        # 构建对象
        bookinfo = BookInfo()
        bookinfo.btitle = book_dict.get('btitle')
        bookinfo.bpub_date = book_dict.get('bpub_date')
        bookinfo.bread = book_dict.get('bread')

        # 保存到数据库中
        bookinfo.save()

        # 序列化返回给前端

        book_dict = {
            'id' : bookinfo.id,
            'btitle' : bookinfo.btitle,
            'bpub_date' : bookinfo.bpub_date,
            'bread' : bookinfo.bread,
            'bcomment' : bookinfo.bcomment,
        }

        return JsonResponse(data=book_dict, status=201)
        pass

class BookDetailView(View):
    '''
    书本详情视图
    '''

    def get(self, request, pk):
        '''
        获取单本书
        :param request:
        :return:
        '''
        try:
            book = BookInfo.objects.get(id=pk)
        except BookInfo.DoesNotExist:
            return HttpResponse(content='没找到对应的书籍', status=404)

        book_dict = {
            'id' : book.id,
            'btitle' : book.btitle,
            'bpub_date' : book.bpub_date,
            'bread' : book.bread,
            'bcomment' : book.bcomment,
        }

        return JsonResponse(data=book_dict)

    def put1(self, request, pk):
        '''
        修改指定的书籍
        :param request:
        :param pk:
        :return:
        '''
        # 查询书籍是否存在
        book = None
        try:
            book = BookInfo.objects.get(id=pk)
        except BookInfo.DoesNotExist :
            return HttpResponse(content='当前书籍不存在', status=404)


        # 反序列化前端传过来的数据
        book_dict = json.loads(request.body.decode())

        # 保存到数据库中
        book = BookInfo()
        book.btitle = book_dict.get('btitle')
        book.bpub_date = book_dict.get('bpub_date')
        book.bread = book_dict.get('bread')

        book.save()

        # 返回序列化数据给前端
        book_dict = {
            'id' : book.id,
            'btitle' : book.btitle,
            'bpub_date' : book.bpub_date,
            'bread' : book.bread,
            'bcomment' : book.bcomment,
        }

        return JsonResponse(data=book_dict, status=200)

        pass

    def put(self, request, pk):
        '''
        修改：使用序列化器
        :param request:
        :param pk:
        :return:
        '''
        book = None
        try:
            book = BookInfo.objects.get(id=pk)
        except BookInfo.DoesNotExist :
            return HttpResponse(content='当前书籍不存在', status=404)

        # 反序列化前端传过来的数据
        book_dict = json.loads(request.body.decode())
        serializer = BookInfoSerializer(instance=book, data=book_dict, partial=True)

        if serializer.is_valid():
            serializer.save()

            return JsonResponse(data=serializer.data)
            pass
        else:
            return HttpResponse('参数校验不通过！%s'%serializer.errors)

        pass

    def delete(self, request, pk):
        '''
        删除指定的书籍
        :param request:
        :return:
        '''
        book = None
        try:
            book = BookInfo.objects.get(id=pk)
        except BookInfo.DoesNotExist :
            return HttpResponse(content='没有找到对应的书籍', status=404)

        book.delete()

        return HttpResponse(status=204)

        pass


class Abc01View(View):
    '''
    测试
    '''

    def get(self, request):
        '''
        测试代码的
        :param request:
        :return:
        '''

        book_dict = {
            'btitle' : 'hahah',
            'bpub_date' : '1999-12-01T10:10:10',
        }
        serializer = self.model_serializer_test(book_dict)

        return JsonResponse(data={'message' : serializer.data})
        pass


    def model_serializer_test(self, book_dict):
        '''
        模型序列化器的使用
        :param book_dict:  输入用例
        :return:
        '''
        book_dict = {
            'btitle' : 'hahah',
            'bpub_date' : '1999-12-01T10:10:10',
        }
        serializer = BookInfo01Serializer(data=book_dict)
        print(serializer.is_valid())
        print(serializer.validated_data)
        print(serializer.data)
        return serializer


def aaa():
    '''
    保存代码
    :return:
    '''
    from booktest.models import HeroInfo, BookInfo

    # 两种方式创建：save 和 create
    # 第一种：save 方法：先创建对象，再调用 save 保存到数据库中
    book = BookInfo(
        btitle='大三国',
        bpub_date='2022-01-02',
    )
    book.save()

    # 第二种：直接调用 create 方法保存
    BookInfo.objects.create(
        btitle='好犀利呢',
        bpub_date='2022-01-02'
    )

    # 带有外键的新增
    # ① 外键字段指定实例对象
    HeroInfo.objects.create(
        hname='大三国01',
        hbook=book
    )

    # ② 外键字段_id=实例对象ID
    HeroInfo.objects.create(
        hname='大三国02',
        hbook_id=book.id
    )
    pass

def bbb():
    '''
    演示基本查询
    :return:
    '''

    from booktest.models import BookInfo

    BookInfo.objects.get(id=1)

    BookInfo.objects.all()

    # 有两种方式进行查询数量
    BookInfo.objects.count()
    BookInfo.objects.all().count()
    pass

def ccc():
    '''
    演示：条件查询
    :return:
    '''

    from booktest.models import BookInfo

    BookInfo.objects.filter(id__exact=1)

    # 模糊查询
    BookInfo.objects.filter(btitle__contains='传')

    # null 查询
    BookInfo.objects.filter(btitle__isnull=False)

    # in 查询
    BookInfo.objects.filter(id__in=[2, 4])

    # 比较查询
    BookInfo.objects.filter(id__gt=3)

    # 不等查询
    BookInfo.objects.exclude(id=3)

    # F 对象
    from  django.db.models import F
    BookInfo.objects.filter(bread__gte=F('bcomment') * 1)

    BookInfo.objects.filter(bread__gte=F('bcomment') /2 + F('bread') /2)

    pass

def ddd():
    '''
    演示：Q 对象进行 OR 查询
    :return:
    '''

    from booktest.models import BookInfo
    from django.db.models import Q

    BookInfo.objects.filter(Q(id__exact=2) | Q(btitle__contains='传'))
    pass

def eee():
    '''
    聚合函数演示
    :return:
    '''

    from booktest.models import BookInfo
    from django.db.models import Sum

    BookInfo.objects.aggregate(Sum('bread'))
    pass

def fff():
    '''
    演示：关联查询
    :return:
    '''

    from booktest.models import BookInfo, HeroInfo

    BookInfo.objects.filter(heroinfo__hname__contains='靖')

    HeroInfo.objects.filter(hbook__btitle__exact='天龙八部')
    pass

def ggg():
    '''
    演示：修改
    :return:
    '''

    from booktest.models import BookInfo

    # 调用 save 方法
    book = BookInfo.objects.get(id=6)
    book.btitle = '好嗨犀利呢'
    book.save()

    # 调用 update 方法
    BookInfo.objects.filter(id=6).update(btitle='好犀利呢！！')

    pass

def hhh():
    '''
    演示：删除的使用
    :return:
    '''

    from booktest.models import BookInfo

    # 模型类对象直接调用 delete 方法
    book = BookInfo.objects.get(id=6)
    book.delete()

    # QuerySet 调用 delete 方法
    BookInfo.objects.filter(id=6).delete()
    pass

def iii():
    '''
    演示限制查询集的使用
    :return:
    '''

    from booktest.models import BookInfo

    queryset = BookInfo.objects.all()[0:2]
    print(queryset.query)
    pass


# ===================================================================


class BookInfoListAPIView(APIView):
    '''
    使用 APIView 来定义视图
    '''

    def get(self, request):
        '''
        get 方法
        :param request:
        :return:
        '''
        # 获取查询参数
        params = request.query_params
        # 获取请求体参数
        data = request.data

        books = BookInfo.objects.all()
        serializer = BookInfoSerializer(instance=books, many=True)

        return Response(serializer.data)
        pass

# 路由：url(r'^books/$', BookInfoListGenericAPIView.as_view()),
class BookInfoListGenericAPIView(GenericAPIView):
    '''
    使用 GenericAPIView 来编写列表视图
    '''

    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer

    def get(self, request):
        '''
        get 方法
        :param request:
        :return:
        '''
        query_set = self.get_queryset()
        serializer = self.get_serializer(query_set, many=True)

        str = ''
        if str:
            print('不为空')
        else:
            print('为空')


        return Response(serializer.data)
        pass

# 路由：url(r'^books/(?P<pk>\d+)/$', BookInfoDetailGenericAPIView.as_view())
class BookInfoDetailGenericAPIView(GenericAPIView):
    '''
    使用 GenericAPIView 来编写详情视图
    '''

    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer

    def get(self, request, pk):
        '''
        获取单个的方法
        :param request:
        :return:
        '''
        book = self.get_object()
        serializer = self.get_serializer(book)

        return Response(data=serializer.data)

        pass


from rest_framework.viewsets import ViewSet, GenericViewSet


class BookInfoViewSet(ViewSet):
    '''
    使用视图集来实现视图方法
    '''

    def list(self, request):
        '''
        查询所有
        :param request:
        :return:
        '''

        books = BookInfo.objects.all()
        serializer = BookInfoSerializer(instance=books, many=True)

        return Response(data=serializer.data)
        pass

    def retrieve(self, request, pk):
        '''
        查询单挑记录
        :param request:
        :param pk:
        :return:
        '''

        book = BookInfo.objects.get(id=pk)
        serializer = BookInfoSerializer(instance=book)

        return Response(data=serializer.data)
        pass

from rest_framework import mixins
class BookInfoGenericViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
    '''
    使用 GenericViewSet 实现
    '''

    queryset = BookInfo.objects.all()
    serializer_class = BookInfoSerializer


    # 最后生成额路由：/books/latest/
    @action(methods=['get'], detail=False)
    def latest(self, request):
        '''
        查询最新的图书
        :param request:
        :return:
        '''

        latest = BookInfo.objects.latest('id')
        serializer = self.get_serializer(instance=latest)

        return Response(data=serializer.data)
        pass

    # 最后生成的路由：/books/<pk>/read/
    @action(methods=['put'], detail=True)
    def read(self, request, pk):
        '''
        获取
        :param request:
        :param pk:
        :return:
        '''
        book = BookInfo.objects.get(id=pk)

        serializer = self.get_serializer(instance=book, data=request.query_params, partial=True)

        if serializer.is_valid():

            serializer.save()
        else:
            return Response(data=serializer.errors)

        return Response(data=serializer.data)
        pass

